package ru.ifmo.segal;

import ru.ifmo.segal.algorithms.Explicit;
import ru.ifmo.segal.algorithms.Implicit;
import ru.ifmo.segal.utils.Segmentation;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;

import static ru.ifmo.network.SwingUtils.getBox;
import static ru.ifmo.network.SwingUtils.getLabeledComponent;

/**
 * @author avhaliullin
 */
public class Configurator extends JFrame {
    private Integer getInt(JSpinner spinner) {
        return ((Number) spinner.getValue()).intValue();
    }

    private Double getDouble(JSpinner spinner) {
        return ((Number) spinner.getValue()).doubleValue();
    }

    public Configurator(final Map<String, Algorithm> algorithms) {
        final JComboBox algorithmChooser = new JComboBox(new Vector<Object>(algorithms.keySet()));
        final JSpinner dt = new JSpinner(new SpinnerNumberModel(0.1, 0.001, 10000, 0.001));
        final JSpinner timeDiscretization = new JSpinner(new SpinnerNumberModel(1000, 10, 100000, 10));
        final JSpinner dx = new JSpinner(new SpinnerNumberModel(0.1, 0.001, 10000, 0.1));
        final JSpinner distanceDiscretization = new JSpinner(new SpinnerNumberModel(2000, 10, 100000, 10));
        final JSpinner u = new JSpinner(new SpinnerNumberModel(1.0, -1000, 1000, 0.1));
        final JSpinner kappa = new JSpinner(new SpinnerNumberModel(0.0, 0, 10, 0.001));

        JButton start = new JButton("Plot");
        start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                List<Double> distribution = new ArrayList<Double>();
                int l = getInt(distanceDiscretization);
                for (int i = 0; i < l; i++) {
                    if (i <= 0.45 * l) {
                        distribution.add(0d);
                    } else if (i <= 0.55 * l) {
                        distribution.add(273d);
                    } else if (i <= 0.65 * l) {
                        distribution.add((0.65 * l - i) / 0.1 * l * 273);
                    } else {
                        distribution.add(0d);
                    }

                }
                new PlotDrawer(algorithms.get(algorithmChooser.getSelectedItem().toString()), new InitialConfig(
                        new Segmentation(0d, getDouble(dt), getInt(timeDiscretization)),
                        new Segmentation(0d, getDouble(dx), getInt(distanceDiscretization)),
                        getDouble(u),
                        getDouble(kappa)),
                        distribution);

            }
        });

        add(getBox(true,
                getLabeledComponent(algorithmChooser, "Algorithm: "),
                getLabeledComponent(distanceDiscretization, "Distance steps: "),
                getLabeledComponent(dx, "dx: "),
                getLabeledComponent(timeDiscretization, "Steps: "),
                getLabeledComponent(dt, "dt: "),
                getLabeledComponent(u, "u: "),
                getLabeledComponent(kappa, "kappa: "),
                start));
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    public void start() {
        setVisible(true);
        getLayout().layoutContainer(this);
        setSize(getPreferredSize().width, getPreferredSize().height + getHeight() - getContentPane().getHeight());
    }

    public static void main(String[] args) {
        Map<String, Algorithm> map = new HashMap<String, Algorithm>();
        map.put("Explicit forward", new Explicit(false));
        map.put("Implicit forward", new Implicit(false));
        map.put("Explicit backward", new Explicit(true));
        map.put("Implicit backward", new Implicit(true));

        new Configurator(map).start();
    }
}
